package com.ngmaster.socket;

import com.ngmaster.socket.util.CRC16;
import com.ngmaster.socket.util.HexByteUtil;

import java.util.Arrays;

/**
 * 协议基础类
 * */
public abstract class ProtocolMessage {

    /** iccid的固定字节数 */
    protected static int icCidLength = 10;

    /** 终端的唯一编号 */
    protected byte[] imeiBytes = new byte[icCidLength];

    /**
     * 明文字符串长度
     * */
    protected String imei;

    /** 命令唯一编号，也可以当做协议的唯一ID */
    protected byte cmd = 0;

    /** 表示data的长度 */
    protected short dataLength = 0;

    protected short crc = 0;

    /** 16进制的crc */
    protected transient String crcHex = "0x00";

    protected ByteArray byteArray = null;

    public byte[] getImeiBytes() {
        return imeiBytes;
    }

    public void setImeiBytes(byte[] imeiBytes) {
        this.imeiBytes = imeiBytes;
    }

    public String getImei() {
        return imei;
    }

    public void setImei(String imei) {
        this.imei = imei;
    }

    public byte getCmd() {
        return cmd;
    }

    public void setCmd(byte cmd) {
        this.cmd = cmd;
    }

    public short getDataLength() {
        return dataLength;
    }

    public void setDataLength(short dataLength) {
        this.dataLength = dataLength;
    }

    public short getCrc() {
        return crc;
    }

    public void setCrc(short crc) {
        this.crc = crc;
    }

    public String getCrcHex() {
        return crcHex;
    }

    public void setCrcHex(String crcHex) {
        this.crcHex = crcHex;
    }

    /**
     * 序列化
     */
    public void serial() {
        byteArray.reset();
        byteArray.writeBytes(this.imeiBytes, 0, this.imeiBytes.length);
        byteArray.writeByte(this.cmd);
        byteArray.writeShort(this.dataLength);
        this.onSerial();
        byte[] writeBytes = new byte[byteArray.getWritePos()];
        System.arraycopy(byteArray.getBytes(), 0, writeBytes, 0, writeBytes.length);
        this.crc = calcCrc16(writeBytes);
        byteArray.writeShort(this.crc);
        this.crcHex = String.format("0x%04x", crc);
    }

    protected short calcCrc16(byte[] writeBytes) {
//        int crc16 = Crc16Util.getCrc16(writeBytes);
        int crc16 = CRC16.calcCrc16(writeBytes);
//        char crc16 = Crc16Util.getCrc16Calc(writeBytes, writeBytes.length);
        return (short) crc16;
    }

    /**
     * 序列化
     */
    public abstract void onSerial();

    /**
     * 反序列化
     */
    public void deserialize() {
        byteArray.reset();
        byteArray.readBytes(this.imeiBytes, 0, this.imeiBytes.length);
        this.cmd = byteArray.readByte();
        this.dataLength = byteArray.readShort();
        this.onDeserialize();
//        byte[] crcBytes = new byte[MessageFrameDecoder.CRC_LENGTH];
//        byteArray.readBytes(crcBytes, 0, crcBytes.length);
        this.crc = byteArray.readShort();  //BitConverter.toShort(crcBytes, 0);
        this.crcHex = String.format("0x%04x", crc);
    }

    /**
     * 反序列化
     */
    public abstract void onDeserialize();

    public ByteArray getByteArray() {
        return byteArray;
    }

    public void setByteArray(ByteArray byteArray) {
        this.byteArray = byteArray;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("ProtocolMessage{");
        sb.append("imeiBytes=").append(Arrays.toString(imeiBytes));
        sb.append(", imei='").append(imei).append('\'');
        sb.append(", cmd=").append(cmd);
        sb.append(", dataLength=").append(dataLength);
        sb.append(", crc=").append(crc);
        sb.append(", crcHex='").append(crcHex).append('\'');
        sb.append(", byteArray=").append(byteArray);
        sb.append('}');
        return sb.toString();
    }

    /**
     * 将接收到到的字符串的ICCID转换成 byte[]的iccid，与客户端进行交互
     * */
    public void convertHexImeiToBytes() {
        this.imeiBytes = HexByteUtil.convertHexStringToBytes(this.imei);
    }
    
    /**
     * 将接收到 byte[]的iccid 转成iccidstr，与客户端进行交互
     * */
    public void convertByteImeiToHex() {
    	this.imei = HexByteUtil.convertBytesToHexString(this.imeiBytes);
    }
}
